using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace ChatClient
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class ChatClientForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.TextBox ChatOut;
		private System.Windows.Forms.StatusBar statusBar1;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.Button btnSend;
		private int serverport;
		private NetworkStream ns;
		private StreamReader sr;
		private TcpClient clientsocket;
		private Thread receive = null;
		private string serveraddress;
		private System.Windows.Forms.ListBox lbChatters;
		private System.Windows.Forms.ListBox lbChannels;
		private System.Windows.Forms.RichTextBox rtbChatIn;
		private string clientname;
		public Dictionary<string, string> channels = new Dictionary<string, string>();
		public Dictionary<string, string[]> channels2 = new Dictionary<string, string[]>();
		private string activechannel = "1";
		//private string destclient;
		private bool connected = false;
		private bool logging = false;
		private bool privatemode = false;
		private System.Windows.Forms.CheckBox cbPrivate;
		private StreamWriter logwriter;
		private bool boolJoin = false;


		public static DialogResult InputBox(string title, string promptText, ref string value)
		{
			Form form = new Form();
			Label label = new Label();
			TextBox textBox = new TextBox();
			Button buttonOk = new Button();
			Button buttonCancel = new Button();
		
			form.Text = title;
			label.Text = promptText;
			textBox.Text = value;
		
			buttonOk.Text = "OK";
			buttonCancel.Text = "Cancel";
			buttonOk.DialogResult = DialogResult.OK;
			buttonCancel.DialogResult = DialogResult.Cancel;
		
			label.SetBounds(9, 20, 372, 13);
			textBox.SetBounds(12, 36, 372, 20);
			buttonOk.SetBounds(228, 72, 75, 23);
			buttonCancel.SetBounds(309, 72, 75, 23);
		
			label.AutoSize = true;
			textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
			buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
			buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
		
			form.ClientSize = new Size(396, 107);
			form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
			form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
			form.FormBorderStyle = FormBorderStyle.FixedDialog;
			form.StartPosition = FormStartPosition.CenterScreen;
			form.MinimizeBox = false;
			form.MaximizeBox = false;
			form.AcceptButton = buttonOk;
			form.CancelButton = buttonCancel;
		
			DialogResult dialogResult = form.ShowDialog();
			value = textBox.Text;
			return dialogResult;
		}

		public ChatClientForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			serverport = 5555;
			disconnectToolStripMenuItem.Enabled = false;
			btnSend.Enabled = false;

		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.cbPrivate = new System.Windows.Forms.CheckBox();
			this.btnSend = new System.Windows.Forms.Button();
			this.lbChatters = new System.Windows.Forms.ListBox();
			this.ChatOut = new System.Windows.Forms.TextBox();
			this.rtbChatIn = new System.Windows.Forms.RichTextBox();
			this.statusBar1 = new System.Windows.Forms.StatusBar();
			this.menuStrip1 = new System.Windows.Forms.MenuStrip();
			this.serverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.connectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.disconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.loggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.startLoggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.stopLoggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.channelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.joinToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.leaveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.commandsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.kickToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
			this.lbChannels = new System.Windows.Forms.ListBox();
			this.menuStrip1.SuspendLayout();
			this.SuspendLayout();
			// 
			// cbPrivate
			// 
			this.cbPrivate.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.cbPrivate.Location = new System.Drawing.Point(491, 386);
			this.cbPrivate.Name = "cbPrivate";
			this.cbPrivate.Size = new System.Drawing.Size(64, 24);
			this.cbPrivate.TabIndex = 10;
			this.cbPrivate.Text = "Private";
			this.cbPrivate.CheckStateChanged += new System.EventHandler(this.cbPrivate_CheckedChanged);
			// 
			// btnSend
			// 
			this.btnSend.Location = new System.Drawing.Point(420, 384);
			this.btnSend.Name = "btnSend";
			this.btnSend.Size = new System.Drawing.Size(64, 24);
			this.btnSend.TabIndex = 5;
			this.btnSend.Text = "Send";
			this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
			// 
			// lbChatters
			// 
			this.lbChatters.Location = new System.Drawing.Point(491, 27);
			this.lbChatters.Name = "lbChatters";
			this.lbChatters.Size = new System.Drawing.Size(88, 355);
			this.lbChatters.TabIndex = 7;
			// 
			// ChatOut
			// 
			this.ChatOut.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.ChatOut.Location = new System.Drawing.Point(106, 386);
			this.ChatOut.Name = "ChatOut";
			this.ChatOut.Size = new System.Drawing.Size(308, 23);
			this.ChatOut.TabIndex = 2;
			this.ChatOut.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ChatOut_KeyPress);
			// 
			// rtbChatIn
			// 
			this.rtbChatIn.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.rtbChatIn.Location = new System.Drawing.Point(106, 27);
			this.rtbChatIn.Name = "rtbChatIn";
			this.rtbChatIn.ReadOnly = true;
			this.rtbChatIn.Size = new System.Drawing.Size(378, 355);
			this.rtbChatIn.TabIndex = 6;
			this.rtbChatIn.Text = "";
			// 
			// statusBar1
			// 
			this.statusBar1.Location = new System.Drawing.Point(0, 415);
			this.statusBar1.Name = "statusBar1";
			this.statusBar1.Size = new System.Drawing.Size(591, 16);
			this.statusBar1.SizingGrip = false;
			this.statusBar1.TabIndex = 3;
			this.statusBar1.Text = "Disconnected";
			// 
			// menuStrip1
			// 
			this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
									this.serverToolStripMenuItem,
									this.loggingToolStripMenuItem,
									this.channelsToolStripMenuItem,
									this.commandsToolStripMenuItem});
			this.menuStrip1.Location = new System.Drawing.Point(0, 0);
			this.menuStrip1.Name = "menuStrip1";
			this.menuStrip1.Size = new System.Drawing.Size(591, 24);
			this.menuStrip1.TabIndex = 12;
			this.menuStrip1.Text = "menuStrip1";
			// 
			// serverToolStripMenuItem
			// 
			this.serverToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
									this.connectToolStripMenuItem,
									this.disconnectToolStripMenuItem});
			this.serverToolStripMenuItem.Name = "serverToolStripMenuItem";
			this.serverToolStripMenuItem.Size = new System.Drawing.Size(51, 20);
			this.serverToolStripMenuItem.Text = "Server";
			// 
			// connectToolStripMenuItem
			// 
			this.connectToolStripMenuItem.Name = "connectToolStripMenuItem";
			this.connectToolStripMenuItem.Size = new System.Drawing.Size(133, 22);
			this.connectToolStripMenuItem.Text = "Connect";
			this.connectToolStripMenuItem.Click += new System.EventHandler(this.ConnectToolStripMenuItemClick);
			// 
			// disconnectToolStripMenuItem
			// 
			this.disconnectToolStripMenuItem.Name = "disconnectToolStripMenuItem";
			this.disconnectToolStripMenuItem.Size = new System.Drawing.Size(133, 22);
			this.disconnectToolStripMenuItem.Text = "Disconnect";
			this.disconnectToolStripMenuItem.Click += new System.EventHandler(this.DisconnectToolStripMenuItemClick);
			// 
			// loggingToolStripMenuItem
			// 
			this.loggingToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
									this.startLoggingToolStripMenuItem,
									this.stopLoggingToolStripMenuItem});
			this.loggingToolStripMenuItem.Name = "loggingToolStripMenuItem";
			this.loggingToolStripMenuItem.Size = new System.Drawing.Size(63, 20);
			this.loggingToolStripMenuItem.Text = "Logging";
			// 
			// startLoggingToolStripMenuItem
			// 
			this.startLoggingToolStripMenuItem.Name = "startLoggingToolStripMenuItem";
			this.startLoggingToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
			this.startLoggingToolStripMenuItem.Text = "Start Logging";
			this.startLoggingToolStripMenuItem.Click += new System.EventHandler(this.StartLoggingToolStripMenuItemClick);
			// 
			// stopLoggingToolStripMenuItem
			// 
			this.stopLoggingToolStripMenuItem.Name = "stopLoggingToolStripMenuItem";
			this.stopLoggingToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
			this.stopLoggingToolStripMenuItem.Text = "Stop Logging";
			this.stopLoggingToolStripMenuItem.Click += new System.EventHandler(this.StopLoggingToolStripMenuItemClick);
			// 
			// channelsToolStripMenuItem
			// 
			this.channelsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
									this.joinToolStripMenuItem,
									this.leaveToolStripMenuItem});
			this.channelsToolStripMenuItem.Name = "channelsToolStripMenuItem";
			this.channelsToolStripMenuItem.Size = new System.Drawing.Size(68, 20);
			this.channelsToolStripMenuItem.Text = "Channels";
			// 
			// joinToolStripMenuItem
			// 
			this.joinToolStripMenuItem.Name = "joinToolStripMenuItem";
			this.joinToolStripMenuItem.Size = new System.Drawing.Size(104, 22);
			this.joinToolStripMenuItem.Text = "Join";
			this.joinToolStripMenuItem.Click += new System.EventHandler(this.JoinToolStripMenuItemClick);
			// 
			// leaveToolStripMenuItem
			// 
			this.leaveToolStripMenuItem.Name = "leaveToolStripMenuItem";
			this.leaveToolStripMenuItem.Size = new System.Drawing.Size(104, 22);
			this.leaveToolStripMenuItem.Text = "Leave";
			this.leaveToolStripMenuItem.Click += new System.EventHandler(this.LeaveToolStripMenuItemClick);
			// 
			// commandsToolStripMenuItem
			// 
			this.commandsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
									this.kickToolStripMenuItem});
			this.commandsToolStripMenuItem.Name = "commandsToolStripMenuItem";
			this.commandsToolStripMenuItem.Size = new System.Drawing.Size(81, 20);
			this.commandsToolStripMenuItem.Text = "Commands";
			// 
			// kickToolStripMenuItem
			// 
			this.kickToolStripMenuItem.Name = "kickToolStripMenuItem";
			this.kickToolStripMenuItem.Size = new System.Drawing.Size(96, 22);
			this.kickToolStripMenuItem.Text = "Kick";
			this.kickToolStripMenuItem.Click += new System.EventHandler(this.KickToolStripMenuItemClick);
			// 
			// lbChannels
			// 
			this.lbChannels.FormattingEnabled = true;
			this.lbChannels.Location = new System.Drawing.Point(12, 27);
			this.lbChannels.Name = "lbChannels";
			this.lbChannels.Size = new System.Drawing.Size(88, 381);
			this.lbChannels.TabIndex = 13;
			this.lbChannels.SelectedIndexChanged += new System.EventHandler(this.LbChannelsSelectedIndexChanged);
			// 
			// ChatClientForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(591, 431);
			this.Controls.Add(this.lbChannels);
			this.Controls.Add(this.cbPrivate);
			this.Controls.Add(this.lbChatters);
			this.Controls.Add(this.rtbChatIn);
			this.Controls.Add(this.btnSend);
			this.Controls.Add(this.statusBar1);
			this.Controls.Add(this.ChatOut);
			this.Controls.Add(this.menuStrip1);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
			this.MainMenuStrip = this.menuStrip1;
			this.Name = "ChatClientForm";
			this.Text = "ChatClient";
			this.Load += new System.EventHandler(this.ChatClientFormLoad);
			this.menuStrip1.ResumeLayout(false);
			this.menuStrip1.PerformLayout();
			this.ResumeLayout(false);
			this.PerformLayout();
		}
		private System.Windows.Forms.ToolStripMenuItem kickToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem commandsToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem leaveToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem joinToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem channelsToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem serverToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem stopLoggingToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem startLoggingToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem loggingToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem disconnectToolStripMenuItem;
		private System.Windows.Forms.ToolStripMenuItem connectToolStripMenuItem;
		private System.Windows.Forms.MenuStrip menuStrip1;
		#endregion
		protected override void OnClosed(EventArgs e)
		{
			QuitChat();
			if(receive != null && receive.IsAlive)
				receive.Abort();
			
			base.OnClosed(e);
		}

		private void EstablishConnection()
		{
			statusBar1.Text = "Connecting to Server";
			try 
			{
				clientsocket = new TcpClient(serveraddress,serverport);
				//clientsocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
				ns = clientsocket.GetStream();
				sr = new StreamReader(ns);
				connected = true;
			}
			catch (Exception e)
			{
				MessageBox.Show("Could not connect to Server","Error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				statusBar1.Text = "Disconnected";
			}
		}
		private void RegisterWithServer()
		{
			try 
			{
				string command = "CONN|" + clientname + "|";
				Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
				ns.Write(outbytes,0,outbytes.Length);
				
				string[] tokens = sr.ReadLine().Trim().Split(new Char[]{'|'});
				if(tokens[0] == "MOTD")
				{
					statusBar1.Text = "Connected";
					disconnectToolStripMenuItem.Enabled = true;
				}
				command = "JOIN|System|"+ clientname + "|\r\n";
				outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
				ns.Write(outbytes,0,outbytes.Length);
				
				activechannel = "System";
				int index = lbChannels.FindString(activechannel);
				if(index == -1)
					MessageBox.Show("Item is not available in ListBox2");
				else
					lbChannels.SetSelected(index,true);
				
				for(int n=1; n<tokens.Length-1; n++)
                    rtbChatIn.AppendText(tokens[n].Trim(new char[] { '\r', '\n' }) + "\r\n");
                statusBar1.Text = "Connected";
                disconnectToolStripMenuItem.Enabled = true;
				this.Text = clientname + ": Connected to Chat Server";
				
			}
			catch (Exception e)
			{
				MessageBox.Show("Error Registering","Error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			}
		}
		
		private void ReceiveChat()
		{
			bool keepalive = true;
			while (keepalive) 
			{
				try
				{
					Byte[] buffer = new Byte[2048];
					ns.Read(buffer,0,buffer.Length);
					string chatter = System.Text.Encoding.ASCII.GetString(buffer);

					string[] tokens = chatter.Split(new Char[]{'|'});

					if (tokens[0] == "CHAT")
					{
						if(tokens[1]==activechannel)
							rtbChatIn.AppendText(tokens[2]);
						else
						{
							if(channels.ContainsKey(tokens[1]))
								channels[tokens[1]] += tokens[2].Trim() + "\r\n";
							else
								channels.Add(tokens[1], tokens[2].Trim() + "\r\n");
						}
						if(logging)
							logwriter.WriteLine(tokens[1] + " " + tokens[2]);
					}
					if (tokens[0] == "PRIV") {
						rtbChatIn.AppendText("Private from ");
						rtbChatIn.AppendText(tokens[1].Trim() );
						rtbChatIn.AppendText(tokens[2] + "\r\n");
						if(logging){
							logwriter.Write("Private from ");
							logwriter.Write(tokens[1].Trim() );
							logwriter.WriteLine(tokens[2] + "\r\n");
						}
					}
					if (tokens[0] == "JOIN")
					{
						string newguy = tokens[2].Trim(new char[]{'\r','\n'});
						if(tokens[1]==activechannel)
						{
							rtbChatIn.AppendText(tokens[2].Trim() );
							rtbChatIn.AppendText(" has joined the Chat\r\n");
							lbChatters.Items.Add(newguy);
							lbChatters.Sorted = true;
						}
						else
						{
							if(channels.ContainsKey(tokens[1]))
							{
								channels[tokens[1]] += tokens[2].Trim();
								channels[tokens[1]] += " has joined the Chat\r\n";
							}
							if(channels2.ContainsKey(tokens[1]))
							{
								var foos = new List<string>(channels2[tokens[1]]);
								foos.Add(newguy);
	                        	foos.Sort();
								channels2[tokens[1]] = foos.ToArray();
							}
						}
						if(logging){
							logwriter.WriteLine(tokens[1] + " " + tokens[2] + " has joined the Chat");
						}
					}
					if (tokens[0] == "KICK")
					{
						string newguy = tokens[2].Trim(new char[]{'\r','\n'});
						if(tokens[2] == clientname)
						{
				            lbChannels.Items.Remove(tokens[1]);
				            lbChannels.EndUpdate();
				            channels.Remove(tokens[1]);
				            channels2.Remove(tokens[1]);
						}
						else
						{
						if(tokens[1]==activechannel)
						{
							rtbChatIn.AppendText(tokens[2].Trim() );
							rtbChatIn.AppendText(" has been kicked from the Chat\r\n");
							lbChatters.Items.Remove(tokens[2].Trim(new char[]{'\r','\n'}));
						}
						else
						{
							if(channels.ContainsKey(tokens[1]))
							{
								channels[tokens[1]] += tokens[2].Trim();
								channels[tokens[1]] += " has been kicked from the Chat\r\n";
							}
							if(channels2.ContainsKey(tokens[1]))
							{
								var foos = new List<string>(channels2[tokens[1]]);
								foos.Remove(newguy);
	                        	foos.Sort();
								channels2[tokens[1]] = foos.ToArray();
							}
						}
						}
						if(logging){
							logwriter.WriteLine(tokens[1] + " " + tokens[2] + " has been kicked from the Chat");
						}
					}
					if (tokens[0] == "LEAV")
					{
						string newguy = tokens[2].Trim(new char[]{'\r','\n'});
						if(tokens[1]==activechannel)
						{
							rtbChatIn.AppendText(tokens[2].Trim() );
							rtbChatIn.AppendText(" has left the Chat\r\n");
							lbChatters.Items.Remove(tokens[1].Trim(new char[]{'\r','\n'}));
						}
						else
						{
							if(channels.ContainsKey(tokens[1]))
							{
								channels[tokens[1]] += tokens[2].Trim() + " has left the Chat\r\n";
							}
							if(channels2.ContainsKey(tokens[1]))
							{
								for (int i = 0; i < channels2[tokens[1]].Length; i++)
									if (channels2[tokens[1]][i] == newguy)
								{
									var foos = new List<string>(channels2[tokens[1]]);
									foos.RemoveAt(i);
									channels2[tokens[1]] = foos.ToArray();
								}
							}
						}
						if(logging){
							logwriter.WriteLine(tokens[1] + " " + tokens[2] + " has left the Chat");
						}
					}
                    if (tokens[0] == "LIST")
                    {
                    	
                    	while (tokens[1] != activechannel)
                    	{
                    	}
	                        var foos = new List<string>(tokens);
	                        foos.RemoveAt(foos.ToArray().Length - 1);
	                        foos.RemoveAt(1);
	                        foos.RemoveAt(0);
	                        foos.Sort();
	                        if(channels2.ContainsKey(activechannel))
	                        	channels2[activechannel] = foos.ToArray();
	                        else
	                        	channels2.Add(activechannel, foos.ToArray());
	                        lbChatters.Items.Clear();
	                        for (int i = 0; i < foos.ToArray().Length; i++)
                    			lbChatters.Items.Add(foos.ToArray()[i]);
                    }
					if (tokens[0] == "QUIT")
					{
						ns.Close();
						clientsocket.Close();
						keepalive = false;
						statusBar1.Text = "Server has stopped";
						connected= false;
						btnSend.Enabled = false;
						lbChatters.Items.Clear();
						connectToolStripMenuItem.Enabled = true;
						disconnectToolStripMenuItem.Enabled = false;
					}
					rtbChatIn.SelectionStart = rtbChatIn.Text.Length;
					rtbChatIn.ScrollToCaret();
				}
				catch(Exception e){}
			}
		}
		private void QuitChat() 
		{
			if(connected) {
				try{
					string command;
					Byte[] outbytes;
					foreach(Object item in lbChannels.Items) {
						command = "LEAV|" + item + "|" + clientname + "|";
						outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
						ns.Write(outbytes,0,outbytes.Length);
					}
						command = "GONE|" + clientname + "|";
						outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
						ns.Write(outbytes,0,outbytes.Length);
					clientsocket.Close();
				}
				catch(Exception ex){
				}
			}
			if(logging)
				logwriter.Close();

			if(receive != null && receive.IsAlive)
				receive.Abort();
			this.Text = "ChatClient";
			
		}
		private void StartStopLogging() 
		{
			if(!logging){
				if(!Directory.Exists("logs"))
					Directory.CreateDirectory("logs");
				string fname = "logs\\" + DateTime.Now.ToString("ddMMyyHHmm") + ".txt";
				logwriter = new StreamWriter(new FileStream(fname, FileMode.OpenOrCreate,
					FileAccess.Write));
				logging = true;
				startLoggingToolStripMenuItem.Enabled = false;
				stopLoggingToolStripMenuItem.Enabled = true;
				statusBar1.Text = "Connected - Log on";
			}
			else{
				logwriter.Close();
				logging = false;
				startLoggingToolStripMenuItem.Enabled = true;
				stopLoggingToolStripMenuItem.Enabled = false;
				statusBar1.Text = "Connected - Log off";
			}

		}
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(String[] args) 
		{
			ChatClientForm cf = new ChatClientForm();
			if(args.Length == 0)
				cf.serveraddress = "localhost";
			else
				cf.serveraddress = args[0];

			Application.Run(cf);
		}


		private void btnSend_Click(object sender, System.EventArgs e)
		{
			try{
				if(!privatemode){
					activechannel = lbChannels.SelectedItem.ToString();
					string pubcommand = "CHAT|" + activechannel + "|" + clientname +": "+ChatOut.Text + "\r\n";
					Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(pubcommand.ToCharArray());
					ns.Write(outbytes,0,outbytes.Length);
					ChatOut.Text = "";
				}
				else{
					if(lbChatters.SelectedIndex == -1){
						MessageBox.Show("Select a chatter name from the list","Error",
							MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
						return;
					}

					string destclient = lbChatters.SelectedItem.ToString();
					string command = "PRIV|" + clientname + "|: " + ChatOut.Text + "|" + destclient;
					Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
					ns.Write(outbytes,0,outbytes.Length);
					ChatOut.Text = "";
				}

			}
			catch(Exception ex){
				MessageBox.Show("Connection with Server lost","Error",
					MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				ns.Close();
				clientsocket.Close();
				if(receive != null && receive.IsAlive)
					receive.Abort();
				connected = false;
				statusBar1.Text = "Disconnected";
			}
		}

		private void ChatOut_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
			if(e.KeyChar == '\r')
				if(connected)
					btnSend_Click(sender, e);
				else
					ConnectToolStripMenuItemClick(sender, e);
		}

		private void cbPrivate_CheckedChanged(object sender, System.EventArgs e) {
			if(cbPrivate.Checked){
				privatemode = true;
			}
			else{
				privatemode = false;
			}
		}

		
		void ChatClientFormLoad(object sender, EventArgs e)
		{
			connectToolStripMenuItem.Enabled = true;
			disconnectToolStripMenuItem.Enabled = false;
			startLoggingToolStripMenuItem.Enabled = true;
			stopLoggingToolStripMenuItem.Enabled = false;
			lbChannels.SelectionMode = System.Windows.Forms.SelectionMode.One;
			lbChannels.Items.Add("System");
			lbChannels.EndUpdate();
		}
				
		void ConnectToolStripMenuItemClick(object sender, System.EventArgs e)
		{
			if(ChatOut.Text == "")
			{
				if(InputBox("Choose Nickname", "Enter your nickname:", ref clientname) != DialogResult.OK)
					return;
			}
			else
				clientname = ChatOut.Text;
			
			EstablishConnection();
			
			if(connected)
			{
				RegisterWithServer();
				receive = new Thread(new ThreadStart(ReceiveChat));
				receive.Start();
				btnSend.Enabled = true;
				connectToolStripMenuItem.Enabled = false;
				disconnectToolStripMenuItem.Enabled = true;
				ChatOut.Text = "";
			}
		}
		
		void DisconnectToolStripMenuItemClick(object sender, EventArgs e)
		{
			QuitChat();
			connectToolStripMenuItem.Enabled = true;
			disconnectToolStripMenuItem.Enabled = false;
			btnSend.Enabled = false;
			ns.Close();
			clientsocket.Close();
			receive.Abort();
			connected = false;
			lbChatters.Items.Clear();
			statusBar1.Text = "Disconnected";
		}
		
		void StartLoggingToolStripMenuItemClick(object sender, EventArgs e)
		{
			StartStopLogging();
		}
		
		void StopLoggingToolStripMenuItemClick(object sender, EventArgs e)
		{
			StartStopLogging();	
		}
		
		void LbChannelsSelectedIndexChanged(object sender, EventArgs e)
		{
			if(channels.ContainsKey(activechannel))
			{
				channels[activechannel] = rtbChatIn.Text;
				string[] chatters = new string[lbChatters.Items.Count];
				lbChatters.Items.CopyTo(chatters, 0);
				channels2[activechannel] = chatters;
			}
			else
			{
				channels.Add(activechannel, rtbChatIn.Text);
				string[] chatters = new string[lbChatters.Items.Count];
				lbChatters.Items.CopyTo(chatters, 0);
				channels2.Add(activechannel, chatters);
			}
			activechannel = lbChannels.SelectedItem.ToString();
			if(channels.ContainsKey(activechannel))
			{
				rtbChatIn.Text = channels[activechannel];
				lbChatters.Items.Clear();
				for(int i = 0; i < channels2[activechannel].Length; i++)
					lbChatters.Items.Add(channels2[activechannel][i]);
			}
			else
			{
				lbChatters.Items.Clear();
				rtbChatIn.Text = "";
			}
			rtbChatIn.SelectionStart = rtbChatIn.Text.Length;
			rtbChatIn.ScrollToCaret();
		}
		
		void JoinToolStripMenuItemClick(object sender, EventArgs e)
		{
            string channel = "";
            if (InputBox("Choose channel", "Enter channel to join:", ref channel) != DialogResult.OK)
                return;
            string pubcommand = "JOIN|" + channel + "|" + clientname + "|\r\n";
            Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(pubcommand.ToCharArray());
            ns.Write(outbytes, 0, outbytes.Length);

            lbChannels.Items.Add(channel);
            lbChannels.EndUpdate();
            channels.Add(channel, "");
            string [] chatters_temp = {"Retrieve chatters failed"};
            if(!channels2.ContainsKey(channel))
            	channels2.Add(channel, chatters_temp);
			int index = lbChannels.FindString(channel);
			if(index == -1)
				MessageBox.Show("Item is not available in ListBox2");
			else
				lbChannels.SetSelected(index,true);
        }
		
		void LeaveToolStripMenuItemClick(object sender, EventArgs e)
		{
            string channel = lbChannels.SelectedItem.ToString();
            if (channel == "System")
				MessageBox.Show("You cannot leave System channel");
            else
            {
			int index = lbChannels.FindString(channel);
			if(index == -1)
				MessageBox.Show("Channel is not available");
			lbChannels.SetSelected(index - 1,true);			
            string pubcommand = "LEAV|" + channel + "|" + clientname + "|\r\n";
            Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(pubcommand.ToCharArray());
            ns.Write(outbytes, 0, outbytes.Length);

            lbChannels.Items.Remove(channel);
            lbChannels.EndUpdate();
            channels.Remove(channel);
            channels2.Remove(channel);
            }
		}
		
		void KickToolStripMenuItemClick(object sender, EventArgs e)
		{
            if (activechannel == "System")
				MessageBox.Show("You cannot kick from System channel");
            else
            {
			string activeuser = lbChatters.SelectedItem.ToString();		
            string pubcommand = "KICK|" + activechannel +  "|" + activeuser + "|" + clientname + "|\r\n";
            Byte[] outbytes = System.Text.Encoding.ASCII.GetBytes(pubcommand.ToCharArray());
            ns.Write(outbytes, 0, outbytes.Length);	
            }
		}	 
	}
}
